package fti.uksw.ruang.fragment;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import android.widget.ViewFlipper;
import fti.uksw.ruang.R;
import fti.uksw.ruang.model.CalendarEvent;
//import android.app.Fragment;

public class MonthViewFragment extends Fragment {

	public static String TAG = MonthViewFragment.class.getName();
	private static String TAGEVENT1 = "EVENT1";

	OnMonthViewListener mCallBack;

	private TextView tvMonthView;
	private TableLayout tl;
	private ViewFlipper viewFlipper;
	private ImageView ivPrevMonth;
	private ImageView ivNextMonth;

	// viewFlipper x value
	private float lastX;

	// create table calendar
	private TableRow[] tr = new TableRow[6];
	private TextView[][][] tv = new TextView[tr.length][7][2];
	private TextView[] tvTitleCal = new TextView[7];

	private static final String DATE_TEMPLATE = "MMM yyyy";
	private SimpleDateFormat sdf = new SimpleDateFormat(DATE_TEMPLATE);

	private static final int DAY_OFFSET = 1;
	private final String[] weekdays = new String[] { "Sun", "Mon", "Tue",
			"Wed", "Thu", "Fri", "Sat" };
	private final String[] months = { "January", "February", "March", "April",
			"May", "June", "July", "August", "September", "October",
			"November", "December" };
	private final int[] daysOfMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,
			30, 31 };
	private List<String> list;
	private int day, month, year;
	private int daysInMonth;
	private int currentDayOfMonth;
	private int currentWeekDay;

	private ArrayList<CalendarEvent> listEvent;
	private Map<String, ArrayList<CalendarEvent>> mapEvent;

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);
		try {
			mCallBack = (OnMonthViewListener) activity;
		} catch (ClassCastException cce) {
			throw new ClassCastException(activity.toString()
					+ " must implement OnMonthViewListener");
		}
	}

	public void onDetach() {
		super.onDetach();
		mCallBack = null;
	}

	public interface OnMonthViewListener {

		public void onCalendarMonthChanged(String detail);

		public void onMontViewEventClick(ArrayList<CalendarEvent> mListKeg);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	}

	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.calmonthview, container, false);

		viewFlipper = (ViewFlipper) v.findViewById(R.id.vfCalMonthView);

		tl = (TableLayout) v.findViewById(R.id.tableMonthViewCal);

		tvMonthView = (TextView) v.findViewById(R.id.textViewMonth_monthView);

		ivNextMonth = (ImageView) v.findViewById(R.id.nextMonth_monthView);
		ivNextMonth.setOnClickListener(ivMonth);
		ivNextMonth.setClickable(true);
		ivNextMonth.setOnTouchListener(onTouchViewFlipper);

		ivPrevMonth = (ImageView) v.findViewById(R.id.prevMonth_monthView);
		ivPrevMonth.setOnClickListener(ivMonth);
		ivPrevMonth.setClickable(true);
		ivPrevMonth.setOnTouchListener(onTouchViewFlipper);

		Calendar calendar = Calendar.getInstance();
		month = calendar.get(Calendar.MONTH);
		year = calendar.get(Calendar.YEAR);
		day = calendar.get(Calendar.DAY_OF_MONTH);
		createMonth(day, month, year);

		return v;
	}

	private OnClickListener ivMonth = new OnClickListener() {

		@Override
		public void onClick(View v) {
			if (v == ivNextMonth) {
				if (month >= 11) {
					month = 0;
					year++;
				} else {
					month++;
				}
				viewFlipper
						.setInAnimation(v.getContext(), R.anim.in_from_right);
				viewFlipper.setOutAnimation(v.getContext(), R.anim.out_to_left);
			} else if (v == ivPrevMonth) {

				if (month <= 0) {
					month = 11;
					year--;
				} else {
					month--;
				}
				viewFlipper
						.setInAnimation(v.getContext(), R.anim.in_from_right);
				viewFlipper.setOutAnimation(v.getContext(), R.anim.out_to_left);
			}
			createMonth(day, month, year);
			addKegiatanToCalendar();
			viewFlipper.setDisplayedChild(1);
		}
	};

	private OnClickListener calendarCellOnClick = new OnClickListener() {

		@Override
		public void onClick(View v) {
			mCallBack.onMontViewEventClick(mapEvent.get(v.getTag() + TAGEVENT1));
		}
	};

	private void createTitleDays() {
		TableLayout.LayoutParams paramTableLayout = new TableLayout.LayoutParams(
				TableLayout.LayoutParams.MATCH_PARENT,
				TableLayout.LayoutParams.MATCH_PARENT);

		TableRow.LayoutParams paramTableRow = new TableRow.LayoutParams(
				TableRow.LayoutParams.MATCH_PARENT,
				TableRow.LayoutParams.MATCH_PARENT, 1);

		TableRow tr = new TableRow(getActivity().getApplicationContext());
		tr.setBackgroundResource(R.drawable.border_table_title_day);
		tr.setOrientation(TableRow.VERTICAL);

		tr.setLayoutParams(paramTableLayout);
		LinearLayout ll = null;
		for (int i = 0; i < weekdays.length; i++) {
			ll = new LinearLayout(getActivity().getApplicationContext());
			ll.setLayoutParams(paramTableRow);
			ll.setOrientation(LinearLayout.VERTICAL);
			ll.setBackgroundResource(R.drawable.border_table_title_day);
			ll.setPadding(0, 0, 0, 0);

			tvTitleCal[i] = new TextView(getActivity().getApplicationContext());
			tvTitleCal[i].setGravity(Gravity.CENTER_HORIZONTAL);
			// tvTitleCal[i].setBackgroundColor(Color.rgb(255, 155, 5));
			tvTitleCal[i].setTextColor(Color.BLACK);
			tvTitleCal[i].setTextSize(getResources().getDimension(
					R.dimen.textsize_calevent_title));
			// setTextAppearance(getActivity()
			// .getApplicationContext(),
			// android.R.style.TextAppearance_Small_Inverse);
			tvTitleCal[i].setLayoutParams(paramTableRow);
			tvTitleCal[i].setPadding(5, 5, 5, 5);
			tvTitleCal[i].setText(weekdays[i]);
			ll.addView(tvTitleCal[i]);
			tr.addView(ll);
			// tr.setBackgroundColor(Color.rgb(255, 255, 50));
		}
		tl.addView(tr);
	}

	private void createTable() {
		// clear table layout
		tl.removeAllViews();
		createTitleDays();

		TableLayout.LayoutParams paramTableLayout = new TableLayout.LayoutParams(
				TableLayout.LayoutParams.MATCH_PARENT,
				TableLayout.LayoutParams.MATCH_PARENT);

		TableRow.LayoutParams paramTableRow = new TableRow.LayoutParams(
				TableRow.LayoutParams.MATCH_PARENT,
				TableRow.LayoutParams.MATCH_PARENT, 1);

		int position = 0;

		for (int i = 0; i < tr.length; i++) {
			tr[i] = new TableRow(getActivity().getApplicationContext());
			tr[i].setClickable(true);

			tr[i].setOrientation(TableRow.VERTICAL);

			paramTableLayout.weight = 1;
			paramTableLayout.height = 0;
			tr[i].setLayoutParams(paramTableLayout);
			tr[i].setPadding(0, 0, 0, 0);

			LinearLayout ll = null;
			for (int j = 0; j < tv[i].length; j++) {
				ll = new LinearLayout(getActivity().getApplicationContext());
				ll.setLayoutParams(paramTableRow);
				ll.setOrientation(LinearLayout.VERTICAL);
				ll.setBackgroundResource(R.drawable.border_table_day);
				ll.setPadding(0, 0, 0, 0);
				ll.setClickable(true);
				ll.setOnClickListener(calendarCellOnClick);
				ll.setOnTouchListener(onTouchViewFlipper);

				for (int k = 0; k < tv[i][j].length; k++) {

					LinearLayout.LayoutParams paramsLinear2 = new LinearLayout.LayoutParams(
							LinearLayout.LayoutParams.MATCH_PARENT,
							LinearLayout.LayoutParams.WRAP_CONTENT);
					paramsLinear2.setMargins(0, 0, 0, 0);

					tv[i][j][k] = new TextView(getActivity()
							.getApplicationContext());

					if (k == 0) {
						tv[i][j][k].setGravity(Gravity.CLIP_VERTICAL);
						paramsLinear2.weight = 0.2f;
					} else {
						tv[i][j][k].setGravity(Gravity.TOP);
						paramsLinear2.weight = 0.75f;
					}
					tv[i][j][k].setLayoutParams(paramsLinear2);
					tv[i][j][k].setWidth(0);
					tv[i][j][k].setHeight(0);
					tv[i][j][k].setPadding(2, 2, 0, 0);
					tv[i][j][k].setIncludeFontPadding(false);
					tv[i][j][k].setTextSize(getResources().getDimension(
							R.dimen.textsize_calevent));
					// tv[i][j][k].setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
					// .setTextAppearance(
					// getActivity().getApplicationContext(),
					// android.R.style.TextAppearance_DeviceDefault_Small);
					ll.addView(tv[i][j][k]);
				}
				String[] dayColor = list.get(position).split("-");
				String theday = dayColor[0];
				String themonth = dayColor[2];
				String theyear = dayColor[3];

				ll.setTag(theday + themonth + theyear);

				tv[i][j][0].setTag(theday);
				tv[i][j][0].setText(theday);
				tv[i][j][1].setTag(theday + themonth + theyear + TAGEVENT1);
				tv[i][j][1].setTextSize(getResources().getDimension(
						R.dimen.textsize_calevent));
				// tv[i][j][1].setTextSize(TypedValue.COMPLEX_UNIT_SP, 10);
				// setTextAppearance(getActivity()
				// .getApplicationContext(),
				// android.R.style.TextAppearance_Small);

				if (dayColor[1].equals("GREY")) {
					for (int k = 0; k < tv[i][j].length; k++) {
						tv[i][j][k].setTextColor(Color.LTGRAY);
					}
				}
				if (dayColor[1].equals("BLACK")) {
					for (int k = 0; k < tv[i][j].length; k++) {
						tv[i][j][k].setTextColor(Color.BLACK);
					}
				}
				if (dayColor[1].equals("BLUE")) {
					for (int k = 0; k < tv[i][j].length; k++) {
						tv[i][j][k].setTextColor(Color.BLUE);
					}
				}

				position++;
				tr[i].addView(ll);
			}

			tl.addView(tr[i]);
		}
	}

	private void createMonth(int day, int _month, int _year) {
		list = new ArrayList<String>();

		Calendar calendar = Calendar.getInstance();
		calendar.set(_year, _month, day);
		Log.d(TAG, "month : " + _month);

		currentDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
		currentWeekDay = calendar.get(Calendar.DAY_OF_WEEK);

		mCallBack.onCalendarMonthChanged(sdf.format(calendar.getTime()));

		tvMonthView.setText(months[_month] + " " + _year);
		Log.d(TAG, sdf.format(calendar.getTime()));

		int trailingspaces = 0;
		int daysInPrevMonth = 0;
		int prevMonth = 0;
		int prevYear = 0;
		int nextMonth = 0;
		int nextYear = 0;

		Log.d(MonthViewFragment.class.getName(), "Current Month: " + _month);
		daysInMonth = daysOfMonth[_month];

		// Gregorian Calendar : set to FIRST OF MONTH
		GregorianCalendar cal = new GregorianCalendar(_year, _month, 1);

		Log.d(MonthViewFragment.class.getName(), "Greg cal: " + cal.getTime());

		if (_month == 11) {
			prevMonth = _month - 1;
			daysInPrevMonth = daysOfMonth[prevMonth];
			nextMonth = 0;
			prevYear = _year;
			nextYear = _year + 1;
		} else if (_month == 0) {
			prevMonth = 11;
			prevYear = _year - 1;
			nextYear = _year;
			daysInPrevMonth = daysOfMonth[prevMonth];
			nextMonth = 1;
		} else {
			prevMonth = _month - 1;
			nextMonth = _month + 1;
			nextYear = _year;
			prevYear = _year;
			daysInPrevMonth = daysOfMonth[prevMonth];
		}

		currentWeekDay = cal.get(Calendar.DAY_OF_WEEK) - 1;
		Log.d(MonthViewFragment.class.getName(), "currentDayOfMonth : "
				+ currentDayOfMonth + " - currentWeekDay : " + currentWeekDay);

		trailingspaces = currentWeekDay;
		Log.d(MonthViewFragment.class.getName(), "Trailing Spaces : "
				+ trailingspaces);

		if (cal.isLeapYear(cal.get(Calendar.YEAR)) && month == 1) {
			++daysInMonth;
		}

		// Trailing Month days
		for (int i = 0; i < trailingspaces; i++) {
			list.add(String
					.valueOf((daysInPrevMonth - trailingspaces + DAY_OFFSET)
							+ i)
					+ "-GREY-" + months[prevMonth] + "-" + prevYear);
			// Log.d(CalMonthViewAct.class.getName(),
			// "Trailing spaces : "
			// + String.valueOf((daysInPrevMonth - trailingspaces + DAY_OFFSET)
			// + i));
		}

		// current month days
		for (int i = 1; i <= daysInMonth; i++) {
			if (i == currentDayOfMonth) {
				list.add(String.valueOf(i) + "-BLUE-" + months[_month] + "-"
						+ year);
			} else {
				list.add(String.valueOf(i) + "-BLACK-" + months[_month] + "-"
						+ year);
			}
			// Log.d(CalMonthViewAct.class.getName(), "Current Month Days : "
			// + String.valueOf(i));
		}

		// leading month days
		int leadingMonthDays = 42 - list.size();
		for (int i = 0; i < leadingMonthDays; i++) {
			list.add(String.valueOf(i + 1) + "-GREY-" + months[nextMonth] + "-"
					+ nextYear);
			// Log.d(CalMonthViewAct.class.getName(), "Leading month days : "
			// + String.valueOf(i + 1));
		}

		createTable();
	}

	private View.OnTouchListener onTouchViewFlipper = new View.OnTouchListener() {

		@Override
		public boolean onTouch(View v, MotionEvent touchEvent) {

			switch (touchEvent.getAction()) {

			case MotionEvent.ACTION_DOWN:
				lastX = touchEvent.getX();
				// Log.d(CalViewAct.class.getName(),
				// "last X : " + touchEvent.getX());
				break;

			case MotionEvent.ACTION_MOVE: {
				float currentX = touchEvent.getX();
				if (lastX == currentX) {
					break;
				} else if ((lastX - currentX) > -20 && (lastX - currentX) < 20) {
					break;
				}
				// if left to right swipe event;
				if (lastX < currentX || v == ivPrevMonth) {
					// set the required Animation type to ViewFlipper
					// the next screen will come in from left and current Screen
					// will go out from right
					viewFlipper.setInAnimation(v.getContext(),
							R.anim.in_from_left);
					viewFlipper.setOutAnimation(v.getContext(),
							R.anim.out_to_right);
					// show the next screen
					if (month <= 0) {
						month = 11;
						year--;
					} else {
						month--;
					}
				}
				// if right to left swipe event
				if (lastX > currentX || v == ivNextMonth) {
					if (viewFlipper.getDisplayedChild() == 0) {
						// set the required animation type to ViewFlipper
						// the next screen will come in from right and current
						// screen will go out from left
						viewFlipper.setInAnimation(v.getContext(),
								R.anim.in_from_right);
						viewFlipper.setOutAnimation(v.getContext(),
								R.anim.out_to_left);
						// show the next screen
						if (month >= 11) {
							month = 0;
							year++;
						} else {
							month++;
						}
					}
				}
				createMonth(day, month, year);
				addKegiatanToCalendar();
				viewFlipper.setDisplayedChild(1);
				break;
			}

			}
			return false;
		}
	};

	public void setListKeg(ArrayList<CalendarEvent> mListEvent) {
		createTable();
		listEvent = mListEvent;
		addKegiatanToCalendar();
	}

	private static final int MAXEVENTINONEDAY = 3;

	private void addKegiatanToCalendar() {
		// List<CalendarEvent> tempListEvent = listEvent;
		mapEvent = new HashMap<String, ArrayList<CalendarEvent>>();

		for (int i = 0; i < listEvent.size(); i++) {
			CalendarEvent _ce = listEvent.get(i);
			Calendar calendarStart = Calendar.getInstance();
			calendarStart.setTime(_ce.getStartTime());
			Calendar calendarStop = Calendar.getInstance();
			calendarStop.setTime(_ce.getEndTime());

			if ((calendarStart.get(Calendar.MONTH) == month && calendarStart
					.get(Calendar.YEAR) == year)
					|| (calendarStop.get(Calendar.MONTH) >= month && calendarStop
							.get(Calendar.YEAR) >= year)
					|| (calendarStop.get(Calendar.YEAR) > year)) {

				// calculate the diff between date
				Calendar _calStart = (Calendar) calendarStart.clone();
				long daysBetWeen = 0;
				// tempCal.
				while (_calStart.before(calendarStop)) {
					_calStart.add(Calendar.DAY_OF_MONTH, 1);
					daysBetWeen++;
				}

				for (int j = 1; j <= daysBetWeen; j++) {
					String tagTextView = calendarStart
							.get(Calendar.DAY_OF_MONTH)
							+ months[calendarStart.get(Calendar.MONTH)]
							+ calendarStart.get(Calendar.YEAR) + TAGEVENT1;

					ArrayList<CalendarEvent> _listEventForMap = mapEvent
							.get(tagTextView);
					if (mapEvent.containsKey(tagTextView)) {
						_listEventForMap = mapEvent.get(tagTextView);
					} else {
						_listEventForMap = new ArrayList<CalendarEvent>();
					}

					TextView tv = (TextView) getView().findViewWithTag(
							tagTextView);

					if (tv != null) {
						String bufferText = tv.getText().toString();
						bufferText += _ce.getSubject() + "\n";
						tv.setText(bufferText);

						_listEventForMap.add(_ce);
						mapEvent.put(tagTextView, _listEventForMap);

					} else {
						// Log.d(TAG, "null text view");
					}
					calendarStart.add(Calendar.DAY_OF_MONTH, 1);
				}

			}

		}
	}
}
